package com.fcy.teamwork.security.access

import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.AccessibilityServiceInfo
import android.accessibilityservice.GestureDescription
import android.accessibilityservice.GestureDescription.StrokeDescription
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Path
import android.graphics.PixelFormat
import android.media.AudioManager
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.Button
import android.widget.FrameLayout
import com.fcy.teamwork.R
import com.fcy.teamwork.base.log
import java.util.*


class AccessibilityCheckNode : AccessibilityService() {
   private var mLayout: FrameLayout? = null


    override fun onUnbind(intent: Intent?): Boolean {
        log("服务结束")
        return super.onUnbind(intent)
    }

    /**
     * 监视点击事件并作出响应
     * @param event
     */
    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        when (event.eventType) {
            AccessibilityEvent.TYPE_VIEW_CLICKED -> {
                //监视点击事件，打印当前点击事件来源于哪个应用
                val packageName = event.packageName.toString()
                val packageManager = this.packageManager
                try {
                    val applicationInfo = packageManager.getApplicationInfo(packageName, 0)
                    val applicationLabel = packageManager.getApplicationLabel(applicationInfo)
                    log(
                        "[点击事件] " + "App name is: " + event.packageName + "(" + applicationLabel + ")"
                    )
                } catch (e: PackageManager.NameNotFoundException) {
                    e.printStackTrace()
                }
                //监视通知事件，打印通知内容，可用于监视聊天通知、短信等
                val texts = event.text
                var content = ""
                if (texts.isNotEmpty()) {
                    for (text in texts) {
                        content += text.toString()
                    }
                }
                log("[通知事件] $content")
            }
            AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED -> {
                val texts = event.text
                var content = ""
                if (texts.isNotEmpty()) {
                    for (text in texts) {
                        content += text.toString()
                    }
                }
                log("[通知事件] $content")
            }
            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {}
            else -> {

            }
        }
        //模拟自动安装apk
        val source = event.source
        if (source != null) {
            val installPage = event.packageName == "com.android.packageinstaller"
            if (installPage) {
                installAPK(event)
            }
        }
    }

    private fun installAPK(event: AccessibilityEvent) {
        val source = rootInActiveWindow
        val installInfos = source.findAccessibilityNodeInfosByText("继续安装")
        nextClick(installInfos)
        val openInfos = source.findAccessibilityNodeInfosByText("打开")
        nextClick(openInfos)
        runInBack(event)
    }

    private fun runInBack(event: AccessibilityEvent) {
        event.source.performAction(GLOBAL_ACTION_BACK)
    }

    private fun nextClick(infos: List<AccessibilityNodeInfo>?) {
        if (infos != null) {
            for (info in infos) {
                if (info.isEnabled && info.isClickable) info.performAction(AccessibilityNodeInfo.ACTION_CLICK)
            }
        }
    }

    override fun onInterrupt() {
        log("Something went wrong")
    }

    /**
     * 用户开启无故障服务时自动触发，此处用于初始化悬浮UI界面
     */
    override fun onServiceConnected() {
        super.onServiceConnected()
        //无障碍服务的配置代码，已通过accessibility_service_config.xml实现
//        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
//        info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED;
//        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
//        info.notificationTimeout = 100;
//        this.setServiceInfo(info);
        val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        mLayout = FrameLayout(this)
        val layoutParams = WindowManager.LayoutParams()
        layoutParams.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
        layoutParams.format = PixelFormat.TRANSLUCENT
        layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
        layoutParams.gravity = Gravity.START
        val inflater = LayoutInflater.from(this)
        inflater.inflate(R.layout.floating_bar, mLayout)
        windowManager.addView(mLayout, layoutParams)
        configurePowerButton()
        configureSimulateTouch()
        configureVolumeButton()
        configureScrollButton()
        configureSwipeButton()
    }

    /**
     * 开启电源管理界面（关机或重启）
     */
    private fun configurePowerButton() {
        val power = mLayout!!.findViewById<View>(R.id.power) as Button
        power.setOnClickListener { performGlobalAction(GLOBAL_ACTION_POWER_DIALOG) }
    }

    /**
     * 调高音量
     */
    private fun configureVolumeButton() {
        val volumeUpButton = mLayout!!.findViewById<View>(R.id.volume_up) as Button
        volumeUpButton.setOnClickListener {
            val audioManager =
                getSystemService(AUDIO_SERVICE) as AudioManager
            audioManager.adjustStreamVolume(
                AudioManager.STREAM_MUSIC,
                AudioManager.ADJUST_RAISE,
                AudioManager.FLAG_SHOW_UI
            )
        }
    }

    /**
     * 模拟向右滑动的手势
     */
    private fun configureSwipeButton() {
        val swipeButton = mLayout!!.findViewById<View>(R.id.swipe) as Button
        swipeButton.setOnClickListener {
            val swipePath = Path()
            swipePath.moveTo(200f, 200f)
            swipePath.lineTo(400f, 200f)
            val gestureBuilder = GestureDescription.Builder()
            gestureBuilder.addStroke(StrokeDescription(swipePath, 0, 500))
            dispatchGesture(gestureBuilder.build(), null, null)
        }
    }

    /**
     * 模拟点击事件
     */
    private fun configureSimulateTouch() {
        val btnSimulateTouch = mLayout!!.findViewById<View>(R.id.simulateTouch) as Button
        btnSimulateTouch.setOnClickListener {
            log("onClick: Simulate Touch")
            val tap = Path()
            tap.moveTo(200f, 200f)
            val tapBuilder = GestureDescription.Builder()
            tapBuilder.addStroke(StrokeDescription(tap, 0, 500))
            dispatchGesture(tapBuilder.build(), null, null)
        }
    }

    /**
     * 模拟下拉刷新的手势
     */
    private fun configureScrollButton() {
        val scrollButton = mLayout!!.findViewById<View>(R.id.scroll) as Button
        scrollButton.setOnClickListener {
            val scrollable = findScrollableNode(rootInActiveWindow)
            scrollable?.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.id)
        }
    }

    private fun findScrollableNode(root: AccessibilityNodeInfo): AccessibilityNodeInfo? {
        val deque: Deque<AccessibilityNodeInfo> = ArrayDeque()
        deque.add(root)
        while (!deque.isEmpty()) {
            val node = deque.removeFirst()
            if (node.actionList.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)) {
                return node
            }
            for (i in 0 until node.childCount) {
                deque.addLast(node.getChild(i))
            }
        }
        return null
    }

    /**
     * 取得正在监控目标包名的AccessibilityService
     */
    private fun getInstalledAccessibilityServiceList(targetPackage: String): List<AccessibilityServiceInfo?> {
        val result: MutableList<AccessibilityServiceInfo?> = ArrayList()
        val accessibilityManager =
            applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        val infoList = accessibilityManager.installedAccessibilityServiceList
        if (infoList == null || infoList.size == 0) {
            return result
        }
        for (info in infoList) {
            if (info.packageNames == null) {
                result.add(info)
            } else {
                for (packageName in info.packageNames) {
                    if (targetPackage == packageName) {
                        result.add(info)
                    }
                }
            }
        }
        return result
    }
}
